package com.woyou.service;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;

import android.util.Log;

import com.woyou.Constants;
import com.woyou.activity.HomeActivity;
import com.woyou.utils.ThreadPoolManager;
import com.woyou.utils.TypeJudgeTools;

public class MessageConnection implements Observed {

	private HomeActivity homeActivity;
	private ArrayList<Observer> observers;
	private Socket socket;
	private PrintWriter out = null;
	private InputStream inputStream;
	public static boolean isInitHeartBeatServer = false;
	public static boolean isNormal = false;
	private String newOrderNo = "";
	/**
	 * 存储新订单的map防止重复接收新订单
	 */
	private HashMap<String, String> newOrderMap = new HashMap<String, String>();
	private String cancelOrderNo = "";
	/**
	 * 存储取消订单的map防止重复接收取消订单
	 */
	private HashMap<String, String> cancelOrderMap = new HashMap<String, String>();
	// 心跳是否断开 false为断开 true为连接
	public static boolean isHeartbeatOk = false;
	public static boolean serverTimeFlag = true;
	public static boolean tryConnect = false;
	private Timer timer;
	private TimerTask timerTask;
	// 线程设置
	public static boolean isRunning = true;
	// 是否第一次连接
	private boolean isFirstConnect = false;
	// 0到20的随机码
	private Random mRandom = new Random();
	private static MessageConnection instance;
	
	/**
	 * 单例模式
	 */
	private MessageConnection() {
		observers = new ArrayList<Observer>();
	}

	public static MessageConnection getInstance() {
		if (instance == null) {
			instance = new MessageConnection();
		}
		return instance;
	}

	/**
	 * 开始连接socket 开始后分别启动三个线程:积极重连、适时接收、适时发送
	 */
	public void startHeartBeatThreads(HomeActivity activity) {
		this.homeActivity = activity;
		isRunning = true;
		// 启动连接线程
		ThreadPoolManager.getInstance().executeTask(new Runnable() {
			@Override
			public void run() {
				startLinkRecursion();
			}
		});

		// 启动发送线程
		ThreadPoolManager.getInstance().executeTask(new Runnable() {
			@Override
			public void run() {
				startSendRecursion();
			}
		});

		// 启动接收线程
		ThreadPoolManager.getInstance().executeTask(new Runnable() {
			@Override
			public void run() {
				startReceiveRecursion();
			}
		});
		// 判断是否第一次连接并且没有网络，开始提示
		timer = new Timer();
		timerTask = new TimerTask() {

			@Override
			public void run() {
				isFirstConnect = false;
				tryConnect = false;
				isHeartbeatOk = false;
				out = null;
				// 打开断网提示
				homeActivity.netHintView.startNetHint();
				Log.i("socketTest", "心跳丢失:" + isHeartbeatOk);
			}
		};
		timer.schedule(timerTask, 12000);
	}

	/**
	 * 启动连接线程
	 * 
	 * @throws Exception
	 */
	public void startLinkRecursion() {
		try {
			while (isRunning) {
				if (!isHeartbeatOk) {
					Log.i("socketTest", "连接socket进了循环");
					isFirstConnect = false;
					if (socket != null) {
						socket.close();
					}
					socket = new Socket();
					Log.i("socketTest", "连接socket");
					socket.connect(new InetSocketAddress(Constants.HEART_BEAT_SERVER,Constants.HEART_BEAT_SERVER_PORT), 4000);
					inputStream = socket.getInputStream();
					isHeartbeatOk = true;
					tryConnect = true;
				}
				Thread.sleep(4000);
			}
		} catch (Exception e) {
			e.printStackTrace();
			// 连接睡眠
			Log.i("socketTest", "连接socket睡4秒");
			try{
				Thread.sleep(4000);
			}catch(Exception e1){
				e.printStackTrace();
			}finally{
				startLinkRecursion();
			}
		}
	}

	/**
	 * 启动发送线程
	 */
	public void startSendRecursion() {
		try {
			while (isRunning) {
				if (isHeartbeatOk || tryConnect) {
					String msg = "";
					if (isFirstConnect) {
						msg = "HP:" + Constants.shopCode + "." + Constants.shopStatus+ "."+ mRandom.nextInt(20);
						Log.i("心跳恢复", "店铺状态设置成功");
					} else {
						msg = "DP:" + Constants.shopCode;
					}
					pushMessage(msg);
					Log.i("socketTest", "发送的信息" + msg);
					if (timer != null) {
						timer.cancel();
						timer=null;
					}
					if(timerTask!=null){
						timerTask.cancel();
						timerTask=null;
					}
					timer = new Timer();
					timerTask = new TimerTask() {
						@Override
						public void run() {
							isFirstConnect = false;
							tryConnect = false;
							isHeartbeatOk = false;
							out = null;
							Log.i("socketTest", "心跳丢失:" + isHeartbeatOk);
							// 打开断网提示
							homeActivity.netHintView.startNetHint();
							//判断是否socket已经断开设置，连接状态
							if(!homeActivity.actionbarView.isSettingShopStatus){
								homeActivity.actionbarView.actionBarController.linkingShopStatus();
							}
						}
					};
					timer.schedule(timerTask, 8000);
				}
				Thread.sleep(9000);
			}
		} catch (Exception e) {
			e.printStackTrace();
			startSendRecursion();
		}

	}

	/**
	 * 接收线程
	 */
	public void startReceiveRecursion() {
		try {
			while (isRunning) {
				if (isHeartbeatOk) {
					String info=new String();
					info = readLine(inputStream);
					if (info != null) {
						if (info.startsWith("DR:")) {
							isFirstConnect = true;
							// 关闭断网提示
							homeActivity.netHintView.stopNetHint();
						}
						if (!info.equals("[ERROR]")) {
							isHeartbeatOk = true;
							Log.i("socketTest", "心跳正常:" + isHeartbeatOk);
							Log.i("socketTest", "接收到消息:" + info);
							processMessage(info);
							if (timer != null) {
								timer.cancel();
								timerTask.cancel();
							}
						}
					}
				}
				Log.i("sleep", "接收去睡觉了");
				Thread.sleep(3000);
			}
		} catch (Exception e) {
			e.printStackTrace();
			startReceiveRecursion();
		}
	}

	/**
	 * 读信息
	 * 
	 * @param in
	 * @return
	 * @throws IOException
	 */
	private String readLine(InputStream in) throws IOException {
		if (in != null) {
			ByteArrayOutputStream buffer = new ByteArrayOutputStream();
			while (true) {
				int b = in.read();
				// 如果数据小于0或者数据没有&符号结尾导致数据过大
				if (b < 0 || (buffer.size() > 2000)) {
					Log.i("socketTest", b + "==" + buffer.size());
					return "[ERROR]";
				}
				// 一直读 直到&符号退出
				if (b == 38) {
					break;
				}
				buffer.write(b);
			}
			buffer.close();
			String data = new String(buffer.toByteArray(), "utf-8");
			return data;
		}
		return null;
	}

	/**
	 * 发送消息给服务器
	 * 
	 * @param message
	 * @throws IOException
	 */
	private synchronized void pushMessage(String message) throws IOException {
		if (out == null) {
			out = new PrintWriter(socket.getOutputStream());
		}
		if (out != null) {
			out.println(message + "&");
			out.flush();
		}
	}

	/**
	 * socket收到推送过来的信息
	 * 
	 * @param message
	 */
	private void processMessage(String message) {

		System.out.println("server: message = " + message);
		String msg = message.trim();
		String msgHead = message.substring(0, 2);
		String msgbody = message.substring(3, msg.length());
		// 新订单
		if (msgHead.startsWith("OK")) {
			if (TypeJudgeTools.isNull(newOrderMap.get(msgbody))) {
				newOrderMap.put(msgbody, msgbody);
				newOrderNo = msgbody;
				// 通知观察者
				notifyObserver(1, newOrderNo);
			}
		}else if (msgHead.startsWith("CL")) {
			// 取消订单
			if (TypeJudgeTools.isNull(cancelOrderMap.get(msgbody))) {
				cancelOrderMap.put(msgbody, msgbody);
				cancelOrderNo = msgbody;
				// 通知观察者
				Log.i("order", msgHead+"=="+msgbody);
				notifyObserver(2, cancelOrderNo);
			}
			try {
				pushMessage("DC:" + msgbody);
			} catch (IOException e) {
				e.printStackTrace();
			}
		} else if (msgHead.startsWith("CT")) {
			// 收到服务器CL后如果回复"DC",服务器收到DC再推送一次CT，不再推送CL
			// 服务器如果没收到"DC",则一直推送CL
		}

	}

	public void returnCustomCancel(String no) {
		try {
			pushMessage("DC:" + no);
			Log.i("information", "返回订单取消");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 关闭socket连接线程
	 */
	public void stopSocket() {
		isRunning = false;
	}

	@Override
	public void registerObserver(Observer o) {
		observers.add(o);
	}

	@Override
	public void removeObserver(Observer o) {
		int i = observers.indexOf(o);
		if (i >= 0) {
			observers.remove(i);
		}
	}

	/**
	 * 通知观察者推送消息
	 * 
	 * @param type
	 *            1:表示新订单 2:表示退单
	 * @param orderNum
	 *            订单编号
	 */
	@Override
	public void notifyObserver(int type, String orderNum) {
		for (int i = 0; i < observers.size(); i++) {
			Observer observer = observers.get(i);
			observer.update(type, orderNum);
		}
	}

}